﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ScFramework.Core;
using System;
/// <summary>
/// 用于管理实体的创建,查询,删除
/// </summary>
public class EntityManager : LogicModuleBase<EntityResource,UserManager>, IEntityManager,IEntityMgrInner,EntityAPI
{
    /// <summary>
    /// 实体集合
    /// </summary>
    Dictionary<UInt16, Entity> entities = new Dictionary<UInt16, Entity>();

    public ISharedCollisionManager sharedCollisionManager => GetInnerModule<ISharedCollisionManager>();

    [RegisterEvent(PhysicsProcessEvent.SyncInstance)]
    void SyncInstance(List<EntityData>es)
    {
        Dictionary<UInt16, EntityData> esdic = new Dictionary<ushort, EntityData>();
        foreach(var x in es)
        {
            esdic[x.EntityIdentity.right()] = x;
        }

        List<UInt16> destoryList = new List<ushort>();
        List<UInt16> removeList = new List<ushort>();
        foreach(var x in entities)
        {

            if (esdic.ContainsKey(x.Key) == false)
            {
                destoryList.Add(x.Key);
            }
         //   else if (x.Value.GetComponent(0) == null || x.Value.GetComponent(0).gameObject == null)
            {
        //        removeList.Add(x.Key);
            }

        }
        DestoryEntities(destoryList);
     //   foreach(var x in removeList)
        {
       //     entities.Remove(x);
        }

        var CreateList = new List<Entity>();
        foreach(var x in es)
        {
            if (entities.ContainsKey(x.EntityIdentity.right()) == false)
            {
                CreateEntity(x);
                CreateList.Add(entities[x.EntityIdentity.right()]);
            }
        }
        if (CreateList.Count > 0) 
        Dispatch(PhysicsProcessEvent.InstancesCreated, CreateList);
        foreach(var x in CreateList)
        {
            x.Start();
        }
    }
    public override void FixedUpdate()
    {
        base.FixedUpdate();
        foreach(var x in entities)
        {
            x.Value.FixedUpdate();
        }
    }

    public override void LateFixedUpdate()
    {
        base.LateFixedUpdate();
        foreach (var x in entities)
        {
            x.Value.LateFixedUpdate();
        }
    }
    void DestoryEntities(List<UInt16> lists)
    {
        if(lists.Count>0)
        Dispatch(PhysicsProcessEvent.InstancesToDelete, lists);
        foreach(var x in lists)
        {

            entities[x].Destory();
            SysModule.DestoryEntity(entities[x]);
            entities.Remove(x);
        }
    }

    /// <summary>
    /// 根据数据生成一个已激活的实体
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    void CreateEntity(EntityData data)
    {
        Debug.Assert(entities.ContainsKey(data.EntityIdentity.right()) == false);
        var e=entities[data.EntityIdentity.right()]=SysModule.CreateEntity(data);
        e.GetComponent(0).gameObject.name = EntityUtilities.GetPrefab(data.EntityIdentity.left()).name;
        e.InitData(data,this);
        e.SetEnable();

    }

    /// <summary>
    /// 清空实体集合
    /// </summary>
    public override void OnDestroy()
    {
        base.OnDestroy();
        entities.Clear();
    }

    public override void OnEnable()
    {
        base.OnEnable();
    //    EntityUtilities.ValueChecker = this;
    }


    public Entity GetEntity(UInt16 id)
    {
        try
        {
            return entities[id];

        }catch(KeyNotFoundException)
        {
            return null;
        }
    }

    [RegisterEvent(PhysicsProcessEvent.Physics_RequireComp)]
    void SendComps(object args=null)
    {
        List<SComponent> comps = new List<SComponent>();
        foreach(var x in entities)
        {
        //    comps.AddRange(x.Value.GetComponents<SRigidUnion>());
            comps.AddRange(x.Value.GetComponents<STransform>());
          //  comps.AddRange(x.Value.GetComponents<SGameObject>());
        }
        Dispatch(PhysicsProcessEvent.Physics_ReceiveComp, comps);
    }

    [RegisterEvent(EntityDataEvent.ValueChanged,order =-1)]
    void SetInstanceValue(ValueChangeArgs args)
    {
        var e = GetEntity(args.EntityID);

        if (e != null&&e.Enable)
        {
            e.GetComponent(args.ValueID.left()).SetInstanceValue(args.ValueID.right(), args.Value);
        }
    }

    public void CreateEntityData(DataCreateArgs args)
    {
        Debug.Assert(SysModule1.IsHost);
        Dispatch(EntityDataEvent.Create, args,false);
    }

    public void DestoryEntityData(ushort args)
    {
        Debug.Assert(SysModule1.IsHost);
        Dispatch(EntityDataEvent.Delete, args,false);
    }

    public List<CollisionArgs> GetCollisionArgs()
    {
        var ans = new List<CollisionArgs>();
        foreach(var x in entities.Values)
        {
            foreach(var y in x.GetComponents<SCollider>())
            {
                ans.AddRange(y.GetCollisionArgs());
            }
        }
        return ans;
    }
}

public interface IEntityMgrInner : IModuleInnerInterface
{
    Entity GetEntity(UInt16 id);

    List<CollisionArgs> GetCollisionArgs();
}
public interface IEntityManager
{
    Entity GetEntity(UInt16 id);
  //  void ChangeValue(UInt16 id, UInt32 valueID, object value);
}

public class EntityChangeArgs:EventArgs
{
    public EntityChangeType ChangeType;
    public object Args;
    public EntityChangeArgs(EntityCreateWithActionArgs args)
    {
        ChangeType = EntityChangeType.CreateWithAction;
        Args = args;
    }

    public EntityChangeArgs(EntityCreateArgs args)
    {
        ChangeType = EntityChangeType.Create;
        Args = args;

    }

    public EntityChangeArgs(EntityCreatedArgs args)
    {
        ChangeType = EntityChangeType.Created;
        Args = args;

    }
    public EntityChangeArgs(EntityDeleteArgs args)
    {
        ChangeType = EntityChangeType.Delete;
        Args = args;

    }
    public EntityChangeArgs(ValueChangeArgs args)
    {
        ChangeType = EntityChangeType.ValueChange;
        Args = args;

    }

}
public enum EntityChangeType
{
    Create,
    Delete,
    ValueChange,


    //from logics to physics
    CreateWithAction,
    //from physics to logics
    Created,
}
public class EntityCreateWithActionArgs
{

    public DataCreateArgs Args;
    public EntityCreateWithActionArgs(DataCreateArgs args)
    {
        Args = args;
    }
}

public class EntityCreatedArgs
{
    public EntityData Data;
    public EntityCreatedArgs(EntityData d)
    {
        Data = d;
    }
}
public class EntityCreateArgs
{
    public UInt32 EntityID;
    public EntityCreateArgs(UInt32 id)
    {
        EntityID = id;
    }
}
public class EntityDeleteArgs
{
    public UInt16 EntityID;
    public EntityDeleteArgs(UInt16 id)
    {
        EntityID = id;
    }
}
public class ValueChangeArgs
{

    public UInt16 EntityID;
    public UInt32 ValueID;
    public object Value;

    public ValueChangeArgs(UInt16 eid,UInt32 vid,object v)
    {
        EntityID = eid;
        ValueID = vid;
        Value = v;
    }
}
